package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.sun.org.apache.regexp.internal.RE;
import com.tanhua.dubbo.db.api.UserInfoApi;
import com.tanhua.dubbo.mongo.api.*;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.mongo.*;
import com.tanhua.model.vo.OptionsVo;
import com.tanhua.model.vo.QuestionsVo;
import com.tanhua.model.vo.ReportVo;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class TestSoulService {

    @DubboReference
    private TestSoulApi testSoulApi;

    @DubboReference
    private QuestionsApi questionsApi;

    @DubboReference
    private OptionsApi optionsApi;

    @DubboReference
    private TypeResultApi typeResultApi;

    @DubboReference
    private ResultTableApi resultTableApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    //查询所有问卷集合
    public List<TestSoulVo> findAll() {

        Long userId = UserHolder.getUserId();


        //1.查询所有问卷 ,根据userId 返回isLock状态
        List<TestSoul> list = testSoulApi.findAll(userId);

        //加入查询出的数据为空 返回空数据
        if (list==null){
            return new ArrayList<TestSoulVo>();
        }

        // 2. 提取所有问卷的id
        List<ObjectId> ids = CollUtil.getFieldValues(list, "id", ObjectId.class);

        //3. 根据问卷的id查询所有对应的试题
        Map<ObjectId, List<QuestionsVo>> questions = findQuestions(ids);

        //4. 构造List<TestSoulVo>  ,返回值
        List<TestSoulVo> vos = new ArrayList<>();

        //返回报告id
        Map<ObjectId,ResultTable> restMap=resultTableApi.findByUserId(userId);

        //一个testSoul 构造一个TestSoulVo
        for (TestSoul testSoul : list) {

            //根据试卷id查询检查报告
            ResultTable resultTable = restMap.get(testSoul.getId());

            List<QuestionsVo> vo = questions.get(testSoul.getId());
            TestSoulVo soulVo = TestSoulVo.init(vo, testSoul);
            //检查报告不为空 ，返回报告id
            if (resultTable!=null){
                soulVo.setReportId(resultTable.getId().toString());
            }
            vos.add(soulVo);
        }

        return vos;
    }

    //根据问卷id查询所有题目的集合
    public Map<ObjectId, List<QuestionsVo>> findQuestions(List<ObjectId> ids) {

        // 1. 获得问卷id和 所对应的试题集合--> List<QuestionsVo>
        Map<ObjectId, List<Questions>> map = questionsApi.findQuestions(ids);

        //2. 构造返回值
        Map<ObjectId, List<QuestionsVo>> mapVo = new HashMap<>();

        // 3. 一个Questions 构建一个QuestionsVo
        for (ObjectId id : ids) {

            List<Questions> questions = map.get(id);

            // 4.1 根据试题id获取答案集合
            List<ObjectId> queIds = CollUtil.getFieldValues(questions, "id", ObjectId.class);

            // 4.2
            Map<ObjectId, List<Options>> opMap = optionsApi.findOptions(queIds);

            //5. 构造QuestionsVo集合
            List<QuestionsVo> list = new ArrayList<>();

            // 5.1 一个question 构造一个QuestionsVo
            for (Questions question : questions) {

                List<Options> options = opMap.get(question.getId());

                //一个Options构建一个OptionsVo
                List<OptionsVo> opVo = new ArrayList<>();
                for (Options option : options) {
                    OptionsVo vo = OptionsVo.init(option);
                    opVo.add(vo);
                }

                QuestionsVo questionsVo = QuestionsVo.init(opVo, question);
                list.add(questionsVo);

            }

            //2.2 构造本方法的返回值
            mapVo.put(id, list);

        }
        return mapVo;
    }


    //测灵魂-提交问卷（学生实战）
    public String submitQuestion(List<Answers> answers) {

        //获取每个试题答案的分数 累加起来  跟据分数保存任务类型  保存到 SimilarYou

        //:类型分数
        int count = 0;

        //获取问卷id
        ObjectId testSoulId = null;
        for (Answers answer : answers) {
            String questionId = answer.getQuestionId();
            //查询问卷id
            testSoulId = questionsApi.findByQuestionId(questionId);
            String optionId = answer.getOptionId();
            //根据试题id和答案id获取答案的分数
            int score = optionsApi.selectByOptionId(questionId, optionId);
            count += score;
        }

        //根据分数查询类型
        TypeResult result = typeResultApi.findbyScore(count);
        Integer type = result.getType();

        //获取用户id和用户数据
        Long userId = UserHolder.getUserId();
        UserInfo userInfo = userInfoApi.findById(userId);

        //将数据保存到结果表中,ResultTable

        //先根据userId和问卷id查询数据库是否有数据，如有数据属于二次答题 ，只更新分数和类型
        ResultTable resultTable = resultTableApi.findResult(userId, testSoulId);


        //赋值，并保存或更新
        String resultId = null;
        if (resultTable == null) {
            //如果没有 保存新数据
            resultTable = new ResultTable();
            resultTable.setUserId(userId.intValue());
            resultTable.setScore(count);
            resultTable.setAvatar(userInfo.getAvatar());
            resultTable.setType(type);
            resultTable.setTestSoulId(testSoulId);
            resultId = resultTableApi.saveResult(resultTable);

        } else {
            //如果有 更新数据 只更新type和分数
            resultId = resultTableApi.updateResult(resultTable, count, type);
        }

        return resultId;

    }

    //测灵魂-查看结果（学生实战）
    public ReportVo report(String id) {

        //根据结果表id查询类型表type
        ResultTable resultTable = resultTableApi.findById(id);
        Integer type = resultTable.getType();

        //根据type查询类型表数据
        TypeResult typeResult = typeResultApi.findBy(type);

        //构造纬度值
        //key->维度项（外向，判断，抽象，理性）
        List<Dimension> dimensions = new ArrayList<>();

        Dimension dimension1 = new Dimension();
        dimension1.setKey("外向");
        dimension1.setValue("60%");
        dimensions.add(dimension1);

        Dimension dimension2 = new Dimension();
        dimension1.setKey("判断");
        dimension1.setValue("80%");
        dimensions.add(dimension2);

        Dimension dimension3 = new Dimension();
        dimension1.setKey("抽象");
        dimension1.setValue("90%");
        dimensions.add(dimension3);

        Dimension dimension4 = new Dimension();
        dimension1.setKey("外向");
        dimension1.setValue("75%");
        dimensions.add(dimension4);

        //构造返回值
        ReportVo reportVo = new ReportVo();
        //构造类型
        reportVo.setConclusion(typeResult.getConclusion());
        reportVo.setCover(typeResult.getCover());
        reportVo.setDimensions(dimensions);

        //构造与你相似
        List<ResultTable> list = resultTableApi.findByType(type);

        List<SimilarYou> similarYous = new ArrayList<>();

        //一个ResultTable 构造一个SimilarYou
        for (ResultTable table : list) {
            SimilarYou you = new SimilarYou();
            you.setUserId(table.getUserId());
            you.setAvatar(table.getAvatar());
            similarYous.add(you);
        }

        reportVo.setSimilarYou(similarYous);

        //返回
        return reportVo;
    }
}
